package view.displayManagers;

import java.awt.Color;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.ImageIcon;
import javax.swing.JButton;

import model.Board;
import controller.ComputerControlledGame;
import controller.Move;

/**
 * Class implements a display manager for automatic game mode
 */
public class AutoGameDisplayTool extends GameDisplayTool implements AutomaticGameDisplayMngr {

	// members
	private ComputerControlledGame gameManager; // game manager	
	private ClickedPiece buttonsToUpdate; // holds data about buttons that should be updated
	private InputOutputMngr ioManager; // manages notifications for the user
	private AtomicBoolean keepPlaying; // indicates if should keep running the game
	
	// public methods

	/**
	 * Constructor- creates a new display manager 
	 * @param iconMap- holds icons for board buttons
	 * @param light- light board button color
	 * @param dark- dark board button color
	 * @param boardSize- game board's size
	 * @param gameManager- reference to game manager
	 * @param boardButtons- board buttons
	 * @param gameBoard- reference to game board
	 */
	public AutoGameDisplayTool(Map<String, ImageIcon> iconMap, Color light, Color dark, int boardSize, ComputerControlledGame gameManager, List<JButton> boardButtons, Board gameBoard) {
		
		// initialize members using base class constructor
		super(iconMap, light, dark, boardSize, boardButtons, gameBoard);
		
		// set game manager
		this.gameManager = gameManager;
		
		// allocate last-to-be clicked button
		buttonsToUpdate = new ClickedPiece(null);
		
		// allocate input-output manager
		this.ioManager = new ContactUser();
		
		// initialize running indicator
		keepPlaying = new AtomicBoolean(true);		
	}
	
	/**
	 * Setting the board buttons in computer-controlled game requires no action listeners
	 */
	@Override
	public List<JButton> setButtons(List<JButton> buttons) {
		
		// no listeners to attach
		return buttons;		
	}

	/**
	 * Sets the board with two-players layout
	 */
	@Override
	public void setBoard() {

		// set standard board for two players
		gameManager.setTowPlayersBoard();
	}
	
	/**
	 * Uses base class's method to refresh the board display, in order
	 * to update the changes
	 */
	@Override
	public void refreshBoardDisplay() {
		
		// update changes
		super.refreshBoardDisplay(buttonsToUpdate);
	}
	
	/**
	 * Runs the automatic game, until reached given maximal turns number or checkmate.
	 * Each turn lasts the given amount of time
	 */
	@Override
	public void runAutomaticGame(int maxTurns, int turnDuration, int interval) {

		// allow the game to run
		keepPlaying.set(true);
		
		// get reference to auto-game display tool
		final AutoGameDisplayTool displayTool = this;
		
		// set delay time for display refresh
		final int delay = turnDuration;
		
		// set bound for turn number
		final int turnNumberBound = maxTurns;
		
		Timer timer = new Timer();
		TimerTask timerTask = new TimerTask() {
			 
			// initialize turn counter
			private int turnCounter = 0;			
			 
			@Override
			public void run() {

				// keep playing until game over or force stop
				while (keepPlaying.get()) {
					
					// make automatic move
					Move move = gameManager.makeMoveComputer();
					
					// update positions to change on board
					buttonsToUpdate.getMoveList().clear();
					buttonsToUpdate.getMoveList().add(move.getSource());
					buttonsToUpdate.getMoveList().add(move.getDestination());
					
					// increment turn counter					
					++turnCounter;
					
					// refresh game board display
					displayTool.refreshBoardDisplay(buttonsToUpdate);
					
					// delay the display
					try {
						Thread.sleep(delay);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					
					// check if game was stopped during the sleep
					if (!keepPlaying.get()) {
						return;
					}
					
					// check if game is over
					
					if (turnCounter >= turnNumberBound) { // check if ends due to number of turns played
						
						// update board display
						displayBoard();
						
						// stop game						
						keepPlaying.set(false);
						cancel();
						
						// notify user
						gameOver("Game over- played " + turnNumberBound + " turns");
						
					} else if (gameManager.isCheckmate()) { // check if ends due to checkmate
						
						// update board display
						displayBoard();
						
						// stop game						
						keepPlaying.set(false);
						cancel();
						
						// notify user
						gameOver("Game over- checkmate");
						
					} else if (gameManager.isStalemate()) { // check if end due to stalemate
						
						// update board display
						displayBoard();
						
						// stop game
						keepPlaying.set(false);
						cancel();
						
						// notify user
						gameOver("Game over- stalemate");
					}
				}
			}			 
		 };
		 		 
		 // run game
		 timer.schedule(timerTask, 0); // TODO use const
	}

	/**
	 * Stops currently running automatic game
	 */
	@Override
	public void stopAutomaticGame() {
		
		// stop game
		keepPlaying.set(false);
	}
	
	/**
	 * Notifies user that game is in Check
	 */
	@Override
	public void notifyCheck() {
		
		// notify user
		ioManager.notifyCheck();
	}

	/**
	 * Uses the input-output manager to notify user that game is over 
	 * and to display given message
	 */
	@Override
	public void gameOver(String msg) {
		
		// notify user
		ioManager.notifyGameOver(msg);
	}
	
	/**
	 * Returns the default option for the piece to replace the Pawn
	 */
	@Override
	public int replacePawn(String[] options, int defualtOption) {
		
		// return the default option
		return defualtOption;
	}
}